/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package assisisw.smartcal.entitysubsystem;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.validation.constraints.NotNull;

@Entity ()
@Table ( name = "calendar" , catalog = "smartcal" )
public class Calendar implements Serializable 
{

    // Static Methods
    
    public static void copySimpleDate ( Calendar src , Calendar dest ) 
    {
        dest.setColor ( src.getColor () ) ;
        dest.setName ( src.getName () ) ;
        dest.setVisible ( src.getVisible () ) ;
    } 
    
    // Instance Fields
    
    /***/
    @Column ( name = "id" , unique = true , updatable = false )
    @GeneratedValue(strategy = GenerationType.TABLE,generator="calendargen")
    @Id
    @TableGenerator ( 
            name = "calendargen" ,
            pkColumnName = "seqname" ,
            pkColumnValue = "calendarseq" ,
            table = "smartcal.sequences" , 
            valueColumnName = "seqnumber" ) 
    private Integer id;

    /***/
    @NotNull
    @Column ( length = 15 , name = "name" , unique = false )
    private String name ;
    
    /***/
    @NotNull
    @Column ( length = 10 , name = "color" , updatable = true )
    private String color ;
    
    /***/
    @NotNull ()
    @Column ( name = "visible" , updatable = true )
    private Boolean visible ;
    
    /***/
    @JoinColumn ( name = "ownerMail" , nullable = false )
    @NotNull
    @ManyToOne ( fetch = FetchType.EAGER , cascade = { CascadeType.DETACH , CascadeType.REFRESH } )
    private User owner ;
    
    /***/
    @NotNull
    @JoinTable ( name = "smartcal.sharedcalendar" ,
                 inverseJoinColumns = { @JoinColumn ( name = "usermail" , referencedColumnName = "mail" ) } ,
                 joinColumns = { @JoinColumn ( name = "calendarid" , referencedColumnName = "id" ) } )
    @ManyToMany ( fetch = FetchType.EAGER , 
                  cascade = { CascadeType.DETACH , CascadeType.MERGE } ,
                  targetEntity = User.class )
    private List < User > peopleWhoCanAccess ;

    /***/
    @NotNull
    @OneToMany ( mappedBy = "owningCalendar" , 
                 fetch = FetchType.EAGER , 
                 cascade = { CascadeType.ALL } )
    private Collection < Event > containedEvents ;

    // Instance Methods
    
    /***/
    public Calendar () 
    {
        peopleWhoCanAccess = new ArrayList <> ( 0 ) ;
        containedEvents = new LinkedList <> () ;
        visible = true ;
    }
    
    /**
     * @param name
     * @param color
     * @throws IllegalArgumentException
     */
    public Calendar ( String name , String color , User owner )
    {
        this () ;
        if ( name != null && color != null && owner != null && ! name.isEmpty () && ! color.isEmpty () ) 
        {
            this.name = name ;
            this.color = color ;
            this.owner = owner ;
        }
        else
            throw new IllegalArgumentException () ;
    }
    
    /**
     * AS THE SUPER'S ONE.
     */
    @Override
    public int hashCode () 
    {
        int hash = 0;
        hash = id.hashCode () ;
        return hash;
    }

    /**
     * AS THE SUPER'S ONE.
     */
    @Override
    public boolean equals ( Object object ) 
    {
        Calendar other ;
        boolean res ;
        if ( object instanceof Calendar )
        {
            other = ( Calendar ) object ;
            if ( id == null || other.getId()==null )
                res = false ;
            else
                res = id == other.getId () ;
        }
        else
            res = false ;
        return res ;
    }

    /**
     * AS THE SUPER'S ONE.
     */
    @Override
    public String toString () 
    {
        return "Calendar : \nId : " + id ;
    }
    
    public void setId ( Integer id ) 
    {
        this.id = id ;
    }
    
    /**
     * @return
     */
    public Integer getId () 
    {
        return id;
    }
    
    /**
     * @param name
     * @throws IllegalArgumentException
     */
    public void setName ( String name ) 
    {
        if ( name != null && ! name.isEmpty () )
            this.name = name ;
        else
            throw new IllegalArgumentException () ;
    }
    
    /***/
    public String getName () 
    {
        return name ;
    }
    
    /***/
    public String getColor () 
    {
        return color ;
    }
    
    /**
     * @param color 
     * @throws IllegalArgumentException
     */
    public void setColor ( String color ) 
    {
        if ( color != null && ! color.isEmpty () )
            this.color = color ;
        else
            throw new IllegalArgumentException () ;
    }
    
    public void setVisible ( Boolean visible ) 
    {
        this.visible = visible ;
    }
    
    public Boolean getVisible () 
    {
        return visible ;
    }
    
    public Boolean isVisible () 
    {
        return visible ;
    }
    
    public void setOwner ( User owner ) 
    {
        this.owner = owner ;
    }
    
    /***/
    public User getOwner () 
    {
        return owner ;
    }
    
    public void setPeopleWhoCanAccess ( List < User > peopleWhoCanAccess ) 
    {
        this.peopleWhoCanAccess = peopleWhoCanAccess ;
    }
    
    public List < User > getPeopleWhoCanAccess () 
    {
        return peopleWhoCanAccess ;
    }
    
    public void setContainedEvents ( Collection < Event > containedEvents ) 
    {
        this.containedEvents = containedEvents ;
    }
    
    public Collection < Event > getContainedEvents () 
    {
        return containedEvents ;
    }
    
}
